#include "device.h"
#include "osal.h"
#include "co_delay.h"
#include "peripheral.h"
#include "arch.h"    // architectural platform definitions
#include "local_lock.h"

static uint32_t volatile g_irq_save;

static co_timer_t lp_timer;
static uint32_t systick_count;

/**
 * @brief  Systick初始化
 *
 * @note
 */
static inline void CPU_SystickInit(uint32_t value)
{
    if (value != 0)
    {
        /* Enable SysTick IRQ and SysTick Timer */
        SysTick->LOAD = value;
        SysTick->VAL = 0UL;
        SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
    }
    else
    {
        /* Disable SysTick */
        SysTick->CTRL  &= ~SysTick_CTRL_ENABLE_Msk;
    }
}

/**
 * @brief  低功耗定时器回调
 *
 * @note
 */
static void CPU_LpTimer(co_timer_t *timer, void *param)
{
    wdt_keepalive();
    Device_IRQHandler(vTIMER_1, NULL, 0);
}
/**
 * @brief systick值初始化
 * 
 * 
 * @note 
 */
void CPU_ClockInit(void)
{
    /* 启动总中断 */
    __enable_irq();
    /* 读取系统时钟 */
    uint32_t sys_clk = cpm_get_clock(CPM_CPU_CLK);
    //__OSAL_LOG("sys_clk: %d\r\n", sys_clk);
    /* 初始化滴答定时器 */
    systick_count = sys_clk / 1000;
    CPU_SystickInit(systick_count);

}
/**
 * @brief  CPU进入睡眠
 *
 * @param  sleep_time：休眠时间
 */
static inline void CPU_EnterSleep(uint32_t sleep_time)
{
    uint32_t t1, t2, past_time;
    if((sleep_time > 0) && (sleep_time <= CO_TIME_SYS2MS(CO_MAX_TIMER_DELAY)))
    {
        co_timer_del(&lp_timer);
        co_timer_set(&lp_timer, sleep_time, TIMER_ONE_SHOT, CPU_LpTimer, NULL);
    }
    /* 休眠前的处理 */
    wdt_enable(0);
    t1 = co_time();                  //< 记录休眠时刻t1
    CPU_SystickInit(0);              //< 关闭systick

    pmu_lowpower_allow(PMU_LP_USER); //< 用户允许休眠

    /* 执行SDK调度（这里面会自己管理进睡眠） */
    rwip_schedule();       


    /* 唤醒后的处理 */
    pmu_lowpower_prevent(PMU_LP_USER);                       //< 用户禁止休眠
    t2 = co_time();                                          //< 记录唤醒时刻t2
    past_time = (uint32_t)(OSAL_PastTime(t2, t1) * 0.03052); //< 计算睡眠时长ms
    OSAL_StepTickCount(past_time);                           //< 补偿systick
    CPU_ClockInit();

}

/**
 * @brief  CPU操作接口
 *
 * @note
 * @param  dev：虚拟设备
 * @param  data：操作类型
 * @param  len：此处没用到
 * @param  param：参数
 * @return 成功/失败
 */
static int32_t CPU_Write(VirtualHardware_enum_t dev, void *data, uint32_t len, uint32_t param)
{
    switch ((uint32_t)data)
    {
    case CPU_SLEEP:
    // __OSAL_LOG("cpu sleep.........\r\n");
        CPU_EnterSleep(param);
        break;

    case CPU_DELAYUS:
        //rwip_schedule();//
        co_delay_us(param);
        break;

    case CPU_DELAYMS:
        rwip_schedule();
        co_delay_ms(param);
        break;

    case CPU_RESET:
        __OSAL_LOG("reset.........\r\n");
        //Local_LockSaveRecord(EVENT_TYPE_PROGRAM, 0XFF, EVENT_CODE_RESET, 0XFF);
        pmu_force_reboot();
        break;

    case CPU_FEEDDOG:
        wdt_keepalive();
        break;

    case CPU_PEND_SV: // Set PendSV to pending
		SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; 
        break;

    default:
        break;
    }
    return 0;
}

/**
 * @brief  开总中断
 */
void Device_EnableIRQ(void)
{
    __set_PRIMASK(g_irq_save);
}

/**
 * @brief  关总中断
 */
void Device_DisableIRQ(void)
{
    g_irq_save = __get_PRIMASK();
    __set_PRIMASK(1);
}

/**
 * @brief  OSAL循环钩子函数
 *
 * @note
 */
void OSAL_LoopHook(void)
{
    rwip_schedule();
    ty_system_mainloop();
}

/**
 * @brief  PendSV中断服务函数
 *
 * @note
 */
void PendSV_Handler(void)
{
    Device_IRQHandler(vCPU_0, NULL, 0);
}

/**
 * @brief  SysTick中断服务函数
 *
 * @note
 */
void SysTick_Handler(void)
{
	Device_IRQHandler(vTIMER_0, NULL, 0);
}

/**
 * @brief  CPU驱动入口
 *
 * @note
 */
static void CPU_Init(void)
{
    /* 定义OSPORT接口 */
    static const VirtualHardware_enum_t vhw_osport[][2] = {
        // #if   defined(R6A40_A) || defined(R6C40_A) || defined(R701B_A)|| defined(R6C20_A)|| defined(R8A90_A)|| defined(MHAH0_LCD)
        // {vUART_1,    vPIN_I1},
        // #else
        // {vBLE_1, vNOHARDWARE},
        //     #ifndef KOS_PARAM_BLE_CLIENT
        // {vBLE_2, vNOHARDWARE},
        // {vBLE_3, vNOHARDWARE},
        // {vBLE_4, vNOHARDWARE},
        //     #endif
        // #endif
		{vUART_1,    vPIN_I1},
        {vNOHARDWARE, vNOHARDWARE}, // 这行必须要（相当于结束符的作用）
    };

    co_delay_init();

    //NVIC_SetPriority(PendSV_IRQn, 0xff);
    // Enable WDT with 10s
    wdt_enable(10);

    CPU_ClockInit();
    NVIC_SetPriority(SysTick_IRQn, 2);

    // Set PendSV to lowest possible priority
    NVIC_SetPriority(PendSV_IRQn, 0xff);

    __OSAL_LOG("mcu reboot reason: %d\r\n", pmu_reboot_reason());

    /* 将底层设备具体操作接口，挂到设备控制块里面 */
    Device_stu_t *dcb = Device_GetDeviceCtrlBlock(vCPU);
    dcb->write = CPU_Write;
    dcb->devParam = (uint32_t)vhw_osport;
}
INIT_BOARD_EXPORT(CPU_Init);
